package vip.liux.backend.application.serviceImpl.shop;

import jakarta.persistence.EntityNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import vip.liux.backend.application.service.shop.*;
import vip.liux.backend.domain.models.shop.address.UserAddress;
import vip.liux.backend.domain.models.shop.address.UserAddressRepository;
import vip.liux.core.current.ICurrentUser;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class AddressServiceImpl implements AddressService {
    private final UserAddressRepository addressRepository;
    private final RegionService regionService;
    private final ICurrentUser<Long> currentUser;

    public AddressServiceImpl(UserAddressRepository addressRepository, RegionService regionService, ICurrentUser<Long> currentUser) {
        this.addressRepository = addressRepository;
        this.regionService = regionService;
        this.currentUser = currentUser;
    }

    @Override
    public List<AddressDto> list() {
        Map<Long, RegionDto> regions = regionService.getCacheAll();
        return addressRepository.findByUserId(currentUser.getId())
                .stream().map(source -> AutoMapperProfile.INSTANCE.toAddressDto(source, regions)).collect(Collectors.toList());
    }

    @Override
    public AddressDto add(ModifyingAddressDto addressDto) {
        UserAddress address = AutoMapperProfile.INSTANCE.toUserAddress(addressDto);
        address.setUserId(currentUser.getId());
        address.setDefaultAddress(!addressRepository.existsNByUserId(currentUser.getId()));
        addressRepository.save(address);
        Map<Long, RegionDto> regions = regionService.getCacheAll();
        return AutoMapperProfile.INSTANCE.toAddressDto(address, regions);
    }

    @Override
    public AddressDto edit(Long addressId, ModifyingAddressDto addressDto) {
        UserAddress address = addressRepository.findById(addressId).orElseThrow(() -> new EntityNotFoundException("Address not found"));
        AutoMapperProfile.INSTANCE.toUserAddress(addressDto, address);
        addressRepository.save(address);
        Map<Long, RegionDto> regions = regionService.getCacheAll();

        return AutoMapperProfile.INSTANCE.toAddressDto(address, regions);
    }

    @Override
    public AddressDto detail(Long addressId) {
        Map<Long, RegionDto> regions = regionService.getCacheAll();
        return AutoMapperProfile.INSTANCE.toAddressDto(addressRepository.findById(addressId).orElseThrow(() -> new EntityNotFoundException("Address not found")), regions);
    }

    @Transactional
    @Override
    public void setDefault(Long addressId) {
        UserAddress address = addressRepository.findById(addressId).orElseThrow(() -> new EntityNotFoundException("Address not found"));
        address.setDefaultAddress(true);

        addressRepository.save(address);
        addressRepository.updateNotDefaultAddress(addressId);
    }

    @Override
    public void remove(Long addressId) {
        UserAddress address = addressRepository.findById(addressId).orElseThrow(() -> new EntityNotFoundException("Address not found"));

        if (address.isDefaultAddress()) {
            throw new IllegalArgumentException("Cannot remove default address");
        }

        addressRepository.deleteById(addressId);
    }
}
